package cn.shujuhai.common.controller.user;

import cn.dev33.satoken.annotation.SaCheckLogin;
import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.dev33.satoken.stp.StpUtil;
import cn.dev33.satoken.util.SaResult;
import cn.shujuhai.common.aop.SysLog;
import cn.shujuhai.common.domain.*;
import cn.shujuhai.common.pluging.data.ResultCode;
import cn.shujuhai.common.pluging.data.ResultVo;
import cn.shujuhai.common.service.DepartmentUserService;
import cn.shujuhai.common.service.SysUserService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.pagehelper.PageInfo;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpSession;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.Collections;
import java.util.List;

/**
 * @Author: NiuYaHu
 * @Date: 2024/12/5 12:01
 * @Description: 针对用户的控制层操作
 **/
@RestController
@RequiredArgsConstructor
@RequestMapping("/user")
public class SysUserController {
    private final SysUserService sysUserService;
    private final DepartmentUserService departmentUserService;

    /**
     * 登录功能
     *
     * @param loginRequest 登录信息
     * @return 登录结果
     */
    @SysLog(value = "用户登录校验", operationType = "登录", module = "登录模块")
    @PostMapping("/login")
    public SaResult login(@Valid @RequestBody LoginRequest loginRequest, HttpSession session, HttpServletRequest request) {
        try {
            // 设置用户IP到session中
            String userIp = request.getRemoteAddr();
            session.setAttribute("userIp", userIp);

            // 调用服务层进行登录处理
            Long userId = sysUserService.login(loginRequest, session);
            if (userId == -100L) {
                return SaResult.error("滑块验证失败，请重试！");
            }
            List<Long> departmentIds = this.departmentUserService.list(new QueryWrapper<DepartmentUser>().lambda().eq(DepartmentUser::getUserId, userId))
                    .stream()
                    .map(DepartmentUser::getDepartmentId)
                    .toList();
            // 检查部门ID集合是否为空
            if (departmentIds.isEmpty()) {
                return SaResult.error("用户没有分配部门");
            }
            // 获取第一个部门ID
            Long firstDepartmentId = departmentIds.getFirst();

            // 将第一个部门ID存储到 Session 中
            session.setAttribute("departmentId", firstDepartmentId);
            StpUtil.login(userId, true);
            StpUtil.getSession().set("username", loginRequest.getUname());
            // 检查密码是否过期
            if (sysUserService.isPasswordExpired(userId)) {
                SaResult result = SaResult.ok("登录成功");
                result.setData(Collections.singletonMap("passwordExpired", true));
                session.setAttribute("passwordExpired", true); // 设置 session 属性
                return result;
            }
            return SaResult.ok("登录成功");
        } catch (RuntimeException e) {
            // 捕获异常并将剩余的登录尝试次数返回给前端
            String message = e.getMessage();
            if (message.contains("剩余尝试次数")) {
                return SaResult.error(message);
            }
            return SaResult.error(e.getMessage());
        }
    }

    /**
     * 检查并处理密码过期
     *
     * @return 操作结果
     */
    @PostMapping("/check-and-handle-password-expiration")
    public ResultVo<?> checkAndHandlePasswordExpiration() {
        Long userId = StpUtil.getLoginIdAsLong();
        int promptCount = sysUserService.checkAndHandlePasswordExpiration(userId);
        System.out.println(promptCount);
        if (promptCount > 3) {
            return ResultVo.failure(ResultCode.ACCOUNT_LOCKED);
        } else if (promptCount == 3) {
            return ResultVo.failure(ResultCode.LAST_PASSWORD_EXPIRE_WARNING);
        } else if (promptCount >= 1) {
            return ResultVo.failure(ResultCode.PASSWORD_EXPIRED);
        }
        return ResultVo.success();
    }

    /**
     * 获取当前登录用户的用户名
     *
     * @return 包含用户名的ResultVo对象
     */
    @GetMapping("/getCurrentUsername")
    public ResultVo<String> getCurrentUsername() {
        Long userId = StpUtil.getLoginIdAsLong();
        String username = sysUserService.getUsernameById(userId);
        if (username != null) {
            return ResultVo.success(username);
        } else {
            return ResultVo.failure(ResultCode.USER_NOT_EXIST);
        }
    }

    /**
     * 获取登录用户的权限集合
     *
     * @return
     */
    @SaCheckPermission("user_list")
    @SysLog(value = "获取登录用户的权限集合", operationType = "查询", module = "用户模块")
    @GetMapping("/permissions")
    public List<String> getPermissions() {
        // 使用sa-token获取当前登录用户的ID
        Object loginId = StpUtil.getLoginId();
        Long userId = Long.parseLong(loginId.toString());
        return this.sysUserService.getPermissionList(userId);
    }

    /**
     * 查询用户列表
     *
     * @param username    用户名
     * @param name        姓名
     * @param pageRequest 分页
     * @return
     */
    @SysLog(value = "用户列表查询", operationType = "查询", module = "用户模块")
    @GetMapping("/list")
    public ResultVo<PageInfo<SysUser>> getSysUserList
    (@Validated String username, @Validated String name, @Valid PageRequest pageRequest, @RequestParam Long departmentId) {
        return this.sysUserService.getSysUserPageInfo(username, name, pageRequest.getPageNum(), pageRequest.getPageSize(), departmentId);

    }

    /**
     * 用户新增
     *
     * @param sysUser 新增用户对象
     * @return 新增用户对象
     */
    @SysLog(value = "用户新增", operationType = "新增", module = "用户模块")
    @PostMapping("/add")
    public ResultVo<Void> save(@RequestBody @Validated(SysUser.CreateGroup.class) SysUser sysUser) {
        return this.sysUserService.add(sysUser);
    }

    /**
     * 用户编辑
     *
     * @param sysUser 编辑用户对象
     * @return 更新用户
     */
    @SysLog(value = "用户编辑", operationType = "编辑", module = "用户模块")
    @PostMapping("/update")
    public ResultVo<SysUser> update(@RequestBody @Validated(SysUser.UpdateGroup.class) SysUser sysUser) {
        return this.sysUserService.edit(sysUser);
    }

    /**
     * 删除用户
     *
     * @param userId 用户Id
     * @return 删除响应结果
     */
    @SysLog(value = "删除用户", operationType = "编辑", module = "用户模块")
    @PostMapping("/delete/{userId}")
    public ResultVo<SysUser> delete(@PathVariable Integer userId) {
        return this.sysUserService.removeId(userId);

    }

    /**
     * 根据用户Id获取用户列表
     *
     * @param userId 用户Id
     * @return
     */
    @SaCheckPermission("user_list")
    @SysLog(value = "根据用户id获取用户列表", operationType = "查询", module = "用户模块")
    @GetMapping("/getUserById/{userId}")
    public ResultVo<SysUser> selectById(@PathVariable Integer userId) {
        return new ResultVo<>(ResultCode.SUCCESS, this.sysUserService.selectById(userId));
    }

    /**
     * 用户启用禁用
     *
     * @param userId 用户Id
     * @return 启用禁用的状态
     */
    @SaCheckPermission("user_enable")
    @SysLog(value = "用户启用禁用", operationType = "编辑", module = "用户模块")
    @PostMapping("/enable/{userId}")
    public ResultVo<SysUser> enableUser(@PathVariable("userId") Integer userId) {
        return this.sysUserService.enableUser(userId);
    }

    /**
     * 用户头像上传
     *
     * @param file 上传的头像文件
     * @return 上传成功后的头像路径
     * @throws IOException
     */
    @SysLog(value = "用户上传头像", operationType = "上传", module = "用户模块")
    @PostMapping("/uploadAvatar")
    public ResultVo<?> uploadAvatarInsert(@RequestParam MultipartFile file) throws IOException {
        return this.sysUserService.uploadAvatar1(file);

    }

    /**
     * 根据用户id获取角色Id
     *
     * @param userId 用户Id
     * @return 角色Id集合
     */
    @SaCheckPermission("user_list")
    @SysLog(value = "根据用户Id获取角色Id", operationType = "查询", module = "用户模块")
    @GetMapping("/getRoleIdsByUserId")
    public ResultVo<?> getRoleIdsByUserId(Long userId) {
        return this.sysUserService.getRoleIdsByUserId(userId);
    }

    /**
     * 登出功能
     *
     * @return 登出结果
     */
    @SysLog(value = "退出登录", operationType = "退出登录", module = "用户模块")
    @PostMapping("/logout")
    public ResultVo<?> logout() {
        StpUtil.logout();
        return new ResultVo<>(ResultCode.SUCCESS, "登出成功");
    }

    /**
     * 用户密码重置
     *
     * @param userId 用户Id
     * @return 重置成功或失败的响应状态
     */

    @SaCheckPermission("user_reset_pwd")
    @SysLog(value = "用户密码重置", operationType = "编辑", module = "用户模块")
    @PostMapping("/resetPwd/{userId}")
    public ResultVo<?> userResetPassword(@PathVariable Long userId) {
        return this.sysUserService.userResetPassword(userId);
    }

    /**
     * 用户密码修改
     *
     * @param oldPwd 用户原始密码
     * @param newPwd 用户新密码
     * @return 修改成功或失败的结果及响应信息
     */
    @SaCheckLogin
    @SysLog(value = "用户密码修改", operationType = "编辑", module = "用户模块")
    @PostMapping("/update_password")
    public ResultVo<?> updatePassword(@RequestParam String oldPwd,
                                      @RequestParam String newPwd) {
        return this.sysUserService.updatePassword(oldPwd, newPwd);
    }

    /**
     * 根据登录用户获取对应的菜单列表
     *
     * @return 用户对应的菜单列表
     */
    @SysLog(value = "根据登录用户获取对应菜单列表", operationType = "查询", module = "用户模块")
    @GetMapping("/getUserMenuByPerm")
    public List<SysMenu> getUserMenuByPerm(HttpServletRequest request) {
        return this.sysUserService.getUserMenuByPerm(request);
    }

    @SysLog(value = "根据登录用户获取对应用户信息", operationType = "查询", module = "用户模块")
    @GetMapping("/getUserByLoginId")
    public ResultVo<SysUser> getUserByLoginId() {
        return this.sysUserService.getUserByLoginId();
    }

    @SysLog(value = "更新登录用户的头像", operationType = "更新", module = "用户")
    @PostMapping("/updateLoginAvatar")
    public ResultVo<SysUser> updateLoginAvatar(String avatar) {
        return this.sysUserService.updateLoginAvatar(avatar);
    }

    @SysLog(value = "更新基本资料", operationType = "更新", module = "用户")
    @PostMapping("/updateUserInfo")
    public ResultVo<SysUser> updateUserInfo(@RequestBody @Validated(SysUser.UpdateGroup.class) SysUser sysUser) {
        return this.sysUserService.updateUserInfo(sysUser);
    }

    @GetMapping("/getUserList")
    public ResultVo<?> getUserList() {
        return this.sysUserService.getUserList();
    }

    @PostMapping("/fpRole")
    public ResultVo<?> fpRole(@RequestBody DepartmentRole departmentRole) {
        return this.sysUserService.fpRole(departmentRole);
    }

    @GetMapping("/getRoleByUserId")
    public ResultVo<?> getRoleByUserId(@RequestParam Long userId) {
        return this.sysUserService.getRoleByUserId(userId);
    }

    @GetMapping("/getUserDepartmentRoles")
    public ResultVo<?> getUserDepartmentRoles(@RequestParam Long userId) {
        return this.sysUserService.getUserDepartmentRoles(userId);
    }

    @PostMapping("/import")
    public ResultVo<?> importUser(@RequestParam("file") MultipartFile file) throws IOException {
        return this.sysUserService.importUser(file);
    }

    @GetMapping("/getUserByDepartmentId")
    public ResultVo<?> getUserByDepartmentId(@RequestParam Long departmentId) {
        return this.sysUserService.getUserByDepartmentId(departmentId);
    }

}